/**
  ******************************************************************************
  * STM32 Bootloader Source
  ******************************************************************************
  * @author Akos Pasztor
  * @file   bootloader.c
  * @brief  This file contains the functions of the bootloader. The bootloader
  *	        implementation uses the official HAL library of ST.
  * @see    Please refer to README for detailed information.
  ******************************************************************************
  * @copyright (c) 2019 Akos Pasztor.                   https://akospasztor.com
  ******************************************************************************
**/

/* Includes ------------------------------------------------------------------*/
#include "loadMain.h"
#include "bootloader.h"
#include <stdio.h>

typedef void (*pFunction)(void);            /*!< Function pointer definition */

void jumpToApplication(void)
{
	/* Private typedef -----------------------------------------------------------*/
    uint32_t  stackAddress = APP_FLASH_BASE;			//	
    uint32_t  resetIrqAddress = stackAddress + 4;		//
    uint32_t  JumpAddress;								//	
    pFunction application;
	
	GLOBAL_DBG("\r\n\r\n!!!jumpToApplication,stackAddr=0x%x!!!!\r\n\r\n",REG32(stackAddress));	
	if((REG32(stackAddress) & 0x2FFE0000)  == SRAM_BASE)  //ApplicationAddress为新程序的起始地址，检查栈顶地址是否合法，即栈顶地址是否为0x2000xxxx（内置SRAM）
	{
		usart_disable(USART0);								//关闭串口
		usart_disable(USART1);			
		__disable_irq();		
		rcu_deinit();										//关闭外设
		
		__set_MSP(REG32(stackAddress));            			//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
		SCB->VTOR = stackAddress;							//重定向中断向量表
		__set_CONTROL(0);									//设置特权模式，sp使用MSP指针
		
		JumpAddress = resetIrqAddress;   					//用户代码区第二个字存储为新程序起始地址（新程序复位向量指针）
		application = (pFunction)REG32(JumpAddress);            
		application();                                		//设置PC指针为新程序复位中断函数的地址
	}	
	else
	{
		GLOBAL_ERR("!!!!!!ERROR:stackAddress ERR,stack=%x!!!!!!!!!\n",REG32(stackAddress));
	}
}

/**
*	function:	跳转到Boot启动
*	作用:	 
*	return :	no
*	返回:	
**/
void jumpToBootloader(void)
{
#if 1	
	__NVIC_SystemReset();
	//nvic_system_reset();	//	直接复位跳转到bootload
#else		
	/* Private typedef -----------------------------------------------------------*/
    uint32_t  stackAddress = BOOTLOAD_BASE_ADDR;			//	
    uint32_t  resetIrqAddress = stackAddress + 4;			//
    uint32_t  bootloadAddr;									//	
    pFunction bootload;
						
	GLOBAL_DBG("\r\n\r\n!!!jumpToBootload,stackAddr=0x%x!!!!\r\n\r\n",REG32(stackAddress));	
	if((REG32(stackAddress) & 0x2FFE0000)  == SRAM_BASE)  	//bootloadAddr为新程序的起始地址，检查栈顶地址是否合法，即栈顶地址是否为0x2000xxxx（内置SRAM）
	{
		usart_disable(USART0);								//关闭串口
		usart_disable(USART1);			
		__disable_irq();		
		rcu_deinit();										//关闭外设
	
		__set_MSP(REG32(stackAddress));            			//初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
		SCB->VTOR = stackAddress;							//重定向中断向量表
		__set_CONTROL(0);									//设置特权模式，sp使用MSP指针
		
		bootloadAddr = resetIrqAddress;   					//用户代码区第二个字存储为新程序起始地址（新程序复位向量指针）
		bootload = (pFunction)REG32(bootloadAddr);            
		bootload();                                		//设置PC指针为新程序复位中断函数的地址
	}	
	else
	{
		GLOBAL_ERR("!!!!!!ERROR:stackAddress ERR,stack=%x!!!!!!!!!\n",REG32(stackAddress));
	}
#endif
}













